package util.instance;

import java.util.ArrayList;
import java.util.Collection;
import org.newdawn.slick.Game;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.state.StateBasedGame;
import util.level.Room;

/**
 * The lowest level on how we keep track of things. An InstanceBag is an unordered list
 * of instances. For adding more complexity such as depth, we can create another data structure
 * which contains instance bags for each level of depth.
 * @author Logan
 */
public class InstanceBag
{
	private ArrayList<Instance> instanceList;
	private ArrayList<Instance> newList;
	
	/**
	 * Creates an empty instance bag.
	 */
	public InstanceBag()
	{
		instanceList=new ArrayList<Instance>();
		newList=new ArrayList<Instance>();
	}
	
	/**
	 * Adds an instance to the bag.
	 * @param i - the instance to add.
	 */
	public void add(Instance i)
	{
		newList.add(i);
	}
	
	/**
	 * Adds multiple instances to the bag at once.
	 * @param collection - a collection containing all the objects to add.
	 */
	public void addAll(Collection<? extends Instance> collection)
	{
		newList.addAll(collection);
	}
	
	/**
	 * Places newly added instances into play.
	 * @param gc - the current game container.
	 * @param sbg - the current game.
	 * @param g - the current graphics.
	 */
	public void refresh(GameContainer gc,StateBasedGame sbg,Room room)
	{
		for(Instance i:newList)
		{
			instanceList.add(i);
			i.creation(gc,sbg,room);
		}
		newList.clear();
	}
	
	/**
	 * Removes destroyed instances from the list and calls their destroy
	 * method.
	 * @param gc - the current game container.
	 * @param sbg - the current game.
	 * @param g - the current graphics.
	 */
	public void prune(GameContainer gc,StateBasedGame sbg,Room room)
	{
		ArrayList<Instance> removeList=new ArrayList<Instance>();
		for(Instance i:instanceList)
			if(i.isDestroyed)
			{
				if(i==room.getViewObject())
				{
					room.setViewObject(null);
					room.setViewOffset(0,0);
				}
				
				i.destroy(gc,sbg,room);
				removeList.add(i);
			}
		instanceList.remove(removeList);
		removeList.clear();
	}
	
	/**
	 * Calls the step method for all of the instances in the list.
	 * @param gc - the current game container.
	 * @param sbg - the current game.
	 * @param g - the current graphics.
	 */
	public void update(GameContainer gc,StateBasedGame sbg,Room room)
	{
		for (int i = 0; i < instanceList.size(); i++)
		{
			instanceList.get(i).step(gc,sbg,room);
		}
		//for(Instance i:instanceList)
		//	i.step(gc,sbg,room);
	}
	
	/**
	 * Calls the end step method for all the instances in the bag.
	 * @param gc - the current game container.
	 * @param sbg - the current game.
	 * @param g - the current graphics.
	 */
	public void endUpdate(GameContainer gc,StateBasedGame sbg,Room room)
	{
		for(Instance i:instanceList)
			i.endStep(gc,sbg,room);
	}
	
	/**
	 * Renders all the objects in the bag.
	 * @param gc - the current game container.
	 * @param sbg - the current game.
	 * @param g - the current graphics.
	 */
	public void render(GameContainer gc,Game game,Graphics g)
	{
		for(Instance i:instanceList)
			i.render(gc,game,g);
		for(Instance i:newList)
			i.render(gc,game,g);
	}
	
	/**
	 * Gets an arrayList containing all of the instances in the list.
	 * @return all the instances in the list
	 */
	public ArrayList<Instance> getList()
	{
		return instanceList;
	}
	
	/**
	 * Gets the size of the bag.
	 * @return the number of instances in the bag.
	 */
	public int getSize()
	{
		return instanceList.size();
	}
	
	/**
	 * Removes all instances from the list.
	 */
	public void removeAll()
	{
		instanceList.clear();
		newList.clear();
	}
}
